package methods;

import items.TermIF;
import items.componentsItem.XTerm;
import items.compositesItem.ProductOfSums;
import items.compositesItem.SumOfProducts;

/**
 * represents the Successive approximation for solving the equation
 * @see EquationSolver
 * @since JDK 1.6
 * @version 1.0
 */
public class SuccessiveApprox extends EquationSolver {

	protected double lamda;
	protected TermIF smallFX;

	public SuccessiveApprox(TermIF equation, double acc) throws NotFoundRootException {
		super(equation, acc);
		lamda();
	}

	public SuccessiveApprox(TermIF equation, double acc, double a, double b) throws NotFoundRootException {
		super(equation, acc);
		this.a = a;
		this.b = b;
		lamda();
	}

	/**
	 * sets the lamda for next computations
	 */
	public void lamda() {
		TermIF diff = equationToSolve.differentiate();
		double first = -2 / diff.evaluate(a);
		double second = -2 / diff.evaluate(b);
		lamda = Math.max(first, second) / 2;
		smallFX = new SumOfProducts(new XTerm(1, 1),
				new ProductOfSums(new XTerm(lamda, 0), equationToSolve));
	}

	@Override
	public double getNext() {
		return smallFX.evaluate(steps.get(steps.size() -1));
	}

	/**
	 * solve by successively substituting the old value
	 * in the function generated by differentiating and adding lamda
	 */
	@Override
	public double solve() {
		double r1 = (a + b) / 2;
		double r2 = smallFX.evaluate(r1);
		steps.add(r1);
		steps.add(r2);
		numberOfSteps++;
		while (Math.abs(r1 - r2) > accuracy) {
			numberOfSteps++;
			r1 = r2;
			r2 = getNext();
			steps.add(r2);
		}
		System.out.println(r2);
		System.out.println(numberOfSteps);
		return r2;
	}
}